from fastapi import FastAPI, APIRouter
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
import asyncio
from database import delete_old_data, SessionLocal
from apscheduler.schedulers.asyncio import AsyncIOScheduler
import os
import httpx  # 用于代理请求
from fastapi.responses import HTMLResponse
from utils import init_mqtt_client
from routers import (
    auth, 
    alerts,
    devicemanage, 
    config, 
    analysis, 
    settings, 
    system,
    devicemanage,
    adminmanage,
    ownedit,
    parameterconfig,
    channel,
    efence,
    efence_alarm,
    realtime,
    face,
    areas
)
# 导入调度器控制函数
from routers.devicemanage import init_device_scheduler, stop_scheduler
from core.logger import app_logger as logger
import urllib.parse
from fastapi.templating import Jinja2Templates

# 注册自定义过滤器
def urldecode_filter(s):
    return urllib.parse.unquote(s)

# 初始化模板
templates = Jinja2Templates(directory="templates")
templates.env.filters["urldecode"] = urldecode_filter

# 创建FastAPI应用实例
app = FastAPI(title="AI视频分析系统", version="1.0")


# ==================== CORS 配置 ====================
# 添加这部分配置解决跨域问题
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:8080",  # 本地开发环境
        "http://192.168.88.105:8080",  # 您的服务器IP
        # 添加其他需要允许的前端域名
    ],
    allow_credentials=True,  # 允许携带凭证（如cookies）
    allow_methods=["*"],  # 允许所有HTTP方法
    allow_headers=["*"],  # 允许所有HTTP头
)

# ==================== 调度器生命周期管理 ====================
app.scheduler = AsyncIOScheduler()  # 创建全局调度器实例

@app.on_event("startup")
async def startup_event():
    """应用启动时执行"""
    # 启动设备状态检查调度器
    from routers.devicemanage import init_device_scheduler
    init_device_scheduler(app.scheduler)  # 使用全局调度器
    
    # 添加数据清理任务
    app.scheduler.add_job(
        delete_old_data_task,
        'interval',
        minutes=30  #每30分钟删一次
    )
    
    app.scheduler.start()  # 只启动一次调度器
    # print("应用启动成功，调度器已运行")
    logger.info("应用启动成功，调度器已运行")
    init_mqtt_client()
    #utils.get_param()

@app.on_event("shutdown")
def shutdown_event():
    """应用关闭时执行"""
    app.scheduler.shutdown()  # 关闭全局调度器
    # print("应用关闭，调度器已停止")
    logger.info("应用关闭，调度器停止")

async def delete_old_data_task():
    db = SessionLocal()
    try:
        logger.info("开始清理过期数据...")
        delete_old_data(db)
        logger.info("过期数据清理完成")
    except Exception as e:
        logger.error(f"数据清理失败: {str(e)}")
    finally:
        db.close()
        
# ==================== 静态文件配置 ====================
current_dir = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(current_dir, "static")
os.makedirs(STATIC_DIR, exist_ok=True)
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")

# ==================== API代理路由（解决跨域问题） ====================
proxy_router = APIRouter(prefix="/proxy", tags=["代理服务"])

@proxy_router.get("/ip")
async def proxy_ip_request():
    """代理请求第三方IP接口，解决跨域问题"""
    try:
        async with httpx.AsyncClient(timeout=10) as client:
            response = await client.get("https://api.yhchj.com/ip")
            return response.json()
    except Exception as e:
        return {"error": f"代理请求失败: {str(e)}", "status_code": 500}

# ==================== 注册所有路由 ====================
# 业务功能路由
app.include_router(auth.router)
app.include_router(alerts.router)
#app.include_router(video.router)
app.include_router(channel.router)
app.include_router(config.router)
app.include_router(analysis.router)
app.include_router(settings.router)
app.include_router(system.router)
app.include_router(devicemanage.router)
app.include_router(adminmanage.router)
app.include_router(ownedit.router)
app.include_router(parameterconfig.router)  
app.include_router(efence.router)
app.include_router(efence_alarm.router)
app.include_router(realtime.router)
app.include_router(face.router)
app.include_router(areas.router)

# 代理服务路由
app.include_router(proxy_router)

# ==================== 应用入口 ====================
if __name__ == "__main__":
    import uvicorn
    # 启动应用，支持自动重载（开发环境）
    uvicorn.run("main:app", host="192.168.88.105", port=8080, reload=True)